#include "board_config.h"

hal_uart_hdl_t const g_board_uart_cons = {
    .pin_txd = {9, _GPIO_DIR_IN, _GPIO_PUD_PULL_UP},
    .pin_rxd = {10, _GPIO_DIR_IN, _GPIO_PUD_PULL_UP},
    .id = 1,
    .irq_prior = 0,
    .br = 115200,
};

#if defined(MIX_PRJ_BOOT)

#include "boot_main.h"
#include "utils/crc32.h"

extern uint8_t _sidata[], _sdata[], _edata[], _sbss[], _ebss[], _estack[];
extern uint8_t _sflash[], _eflash[];

boot_info_t const g_boot_info = {

    .boot_ver_str = BOOT_VER,        // boot 程序协议版本
    .platform_str = "MDK-STM32F103", // 平台名称（如 "STM32F103"）
    .firmware_str = "FW0001",        // 定义适配的固件名称，（如 "FW0001"）

    .uart_default_br = 115200, // 默认波特率
    .uart_bus_clk = 3000000,   // 串口总线频率，用于计算串口的最大波特率
    .uart_bus_div = 1,         // 串口最小分频系数

    .payload_size = BOOT_CMD_PAYLOAD_SIZE, // 最大一次数据传输数

    .wdg_ms = 0, // 上电启动看门狗的超时时间，单位为毫秒，为0时表示不启动
};

static void _port_uart_init(void);
static void _port_uart_set_rx_cb(void (*cb)(void));
static void _port_uart_set_br(u32_t clk, u32_t br);
static int _port_uart_read(u8_t *dst);
static void _port_uart_send(const void *src, uint size);

static void _port_wdt_start(u16_t ms);

boot_port_t const g_boot_port = {
    .uart = {
        .init = _port_uart_init,
        .set_rx_cb = _port_uart_set_rx_cb,
        .set_br = _port_uart_set_br,
        .read = _port_uart_read,
        .send = _port_uart_send,
    },
    .img = {
        .addr_base = 0,
        .get_sector_base = drv_fmc_get_sector_base,
        .get_sector_size = drv_fmc_get_sector_size,
        .sector_erase = drv_fmc_sector_erase,
        .data_write = drv_fmc_data_write,
        .data_read = drv_fmc_data_read,
    },
    .rom = {
        .addr_base = (u32_t)&_eflash[BOOT_CMD_PAYLOAD_SIZE],
        .get_sector_base = drv_fmc_get_sector_base,
        .get_sector_size = drv_fmc_get_sector_size,
        .sector_erase = drv_fmc_sector_erase,
        .data_write = drv_fmc_data_write,
        .data_read = drv_fmc_data_read,
    },
    .cfg = {
        .addr_base = (u32_t)_eflash,
        .get_sector_base = drv_fmc_get_sector_base,
        .get_sector_size = drv_fmc_get_sector_size,
        .sector_erase = drv_fmc_sector_erase,
        .data_write = drv_fmc_data_write,
        .data_read = drv_fmc_data_read,
    },
    .flash_unlock = drv_fmc_unlock,
    .wdt_start = _port_wdt_start,
    .wdt_reload = wdt_reload,
    .get_cpu_clk = drv_clk_get_cpu_clk,
    .sys_reset = drv_hal_sys_reset,
    .crc32_calc = crc32_calc,
};

static void _port_uart_init(void)
{
    do
    {
        uart_param_t uart_param = {
            .br = g_board_uart_cons.br,
            .length = 8,    /* 7..9 */
            .stop_bit = 1,  /* 1 or 2 */
            .parity = 0,    /* 0: none 1: even  2: odd */
            .flow_ctrl = 0, /* 0: none 1: RTS 2: CTS 3: RTS+CTS */
        };

        drv_uart_enable(g_board_uart_cons.id);
        drv_uart_init(g_board_uart_cons.id, &uart_param);

        drv_uart_irq_tx_disable(g_board_uart_cons.id);
        drv_uart_irq_rx_enable(g_board_uart_cons.id, 0);

        drv_uart_pin_configure_txd(g_board_uart_cons.id, g_board_uart_cons.pin_txd.pin);
        drv_uart_pin_configure_rxd(g_board_uart_cons.id, g_board_uart_cons.pin_rxd.pin);

    } while (0);
}

static void _port_uart_set_rx_cb(void (*cb)(void))
{
    drv_uart_irq_callback_enable(g_board_uart_cons.id, cb);
}

static void _port_uart_set_br(u32_t clk, u32_t br)
{
    drv_uart_set_br(g_board_uart_cons.id, clk, br);
}

static int _port_uart_read(u8_t *dst)
{
    if (drv_uart_is_rx_ready(g_board_uart_cons.id))
    {
        return drv_uart_poll_read(g_board_uart_cons.id, dst);
    }
    else
    {
        return 1;
    }
}

static void _port_uart_send(const void *src, uint size)
{
    drv_uart_fifo_fill(g_board_uart_cons.id, src, size);
}

static void _port_wdt_start(u16_t ms)
{
    wdt_enable();
    wdt_set_config(_WDT_MODE_RESET, ms, ms);
}

#endif /* #if defined(MIX_PRJ_BOOT) */
